﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using jp110311.StorageModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace MvcWebRole1.Tests.Services
{
    /// <summary>
    /// BbsEntityServiceTest の概要の説明
    /// </summary>
    [TestClass]
    public class BbsEntityServiceTest
    {
        /// <summary>
        ///現在のテストの実行についての情報および機能を
        ///提供するテスト コンテキストを取得または設定します。
        ///</summary>
        public TestContext TestContext { get; set; }

        #region 追加のテスト属性
        //
        // テストを作成する際には、次の追加属性を使用できます:
        //
        // クラス内で最初のテストを実行する前に、ClassInitialize を使用してコードを実行してください
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // クラス内のテストをすべて実行したら、ClassCleanup を使用してコードを実行してください
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 各テストを実行する前に、TestInitialize を使用してコードを実行してください
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 各テストを実行した後に、TestCleanup を使用してコードを実行してください
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion


        [TestInitialize()]
        public void MyTestInitialize()
        {
            CloudStorageAccount account = CloudStorageAccount.DevelopmentStorageAccount;
            CloudTableClient client = account.CreateCloudTableClient();
            var tables = client.ListTables().ToList();
            foreach (var table in tables)
            {
                client.DeleteTableIfExist(table);
                client.CreateTableIfNotExist(table);
            }            
        }

        [TestMethod]
        public void TestPostTimeConfrict()
        {
            BbsEntityServices.UseDevelopmentStorage = true;
            DateTime postAt = DateTime.Now;
            BbsEntityServices.AddBbsMessage( "1234567", postAt, "test1", "test", "1234567","aaaa" );
            BbsEntityServices.AddBbsMessage( "1234567", postAt, "test2", "test", "1234567","aaaa" );

            int count = BbsEntityServices.GetBbsEntitiesCount("1234567");
            Assert.AreEqual(2, count);

            var entities = BbsEntityServices.GetBbsEntities("1234567", 0, 20).ToList();
            Assert.AreEqual(2,entities.Count);
            Assert.AreEqual("test2", entities[0].Title);
            Assert.AreEqual("test1", entities[1].Title);

            entities = BbsEntityServices.GetBbsEntities("1234567", 0, 1).ToList();
            Assert.AreEqual(1, entities.Count);
            Assert.AreEqual("test2", entities[0].Title);
            entities = BbsEntityServices.GetBbsEntities("1234567", 1, 1).ToList();
            Assert.AreEqual(1, entities.Count);
            Assert.AreEqual("test1", entities[0].Title);
        }

        [Ignore()] // credential/ key をつぶしたので
        [TestMethod]
        public void TestPostTimeConfrictReal()
        {
            var account = new CloudStorageAccount(
                    new StorageCredentialsAccountAndKey(
                        "", 
                        ""),
                        true);
            BbsEntityServices.GetAccountDelegate = () => account;
            CloudTableClient client = account.CreateCloudTableClient();
            var tables = client.ListTables().ToList();
            foreach (var table in tables)
            {
                client.DeleteTableIfExist(table);
                bool success = false;
                do
                {
                    try
                    {
                        client.CreateTableIfNotExist(table);
                        success = true;
                    }
                    catch
                    {
                        System.Threading.Thread.Sleep(1000);
                    }
                } while (!success);
            }
            var altContext = client.GetDataServiceContext();
            altContext.IgnoreResourceNotFoundException = true;

            BbsEntityServices.BeforeSaveChanges += (s,e)=>
            {
                // 更新衝突の再現の為に INDEX を更新する
                var qidx = altContext.CreateQuery<BbsIndexEntity>(BbsEntityServices.BbsEntityTableName);
                var indexEntity = qidx.Where(idx => idx.PartitionKey == "1234567" && idx.RowKey == "INDEX").SingleOrDefault();
                if (indexEntity == null)
                {
                    altContext.AddObject(BbsEntityServices.BbsEntityTableName, new BbsIndexEntity("1234567") );
                }
                altContext.SaveChanges();
            };

            DateTime postAt = DateTime.Now;
            BbsEntityServices.AddBbsMessage("1234567", postAt, "test1", "test", "1234567", "aaaa");
            BbsEntityServices.AddBbsMessage("1234567", postAt, "test2", "test", "1234567", "aaaa");

            int count = BbsEntityServices.GetBbsEntitiesCount("1234567");
            Assert.AreEqual(2, count);

            var entities = BbsEntityServices.GetBbsEntities("1234567", 0, 20).ToList();
            Assert.AreEqual(2, entities.Count);
            Assert.AreEqual("test2", entities[0].Title);
            Assert.AreEqual("test1", entities[1].Title);
        }


        [TestMethod]
        public void TestAddRemoveTag()
        {
            BbsEntityServices.UseDevelopmentStorage = true;
            DateTime postAt = DateTime.Now;
            BbsEntityServices.AddBbsMessage("1234567", postAt, "test1", "test", "1234567", "aaaa");
            string msgIdTest2 = BbsEntityServices.AddBbsMessage("1234567", postAt, "test2", "test", "1234567", "aaaa");

            var entities = BbsEntityServices.GetBbsEntities("1234567", 0, 20).ToList();
            Assert.AreEqual(msgIdTest2, entities[0].RowKey);
            BbsEntityServices.AddTagToBbsEntity("1234567", msgIdTest2, "tag1");

            var tags = BbsEntityServices.GetBbsTags("1234567", 0, 20);
            Assert.AreEqual(1,tags.Count());

            BbsEntityServices.AddTagToBbsEntity("1234567", msgIdTest2, "tag2");

            tags = BbsEntityServices.GetBbsTags("1234567", 0, 20);
            Assert.AreEqual(2, tags.Count());

            tags = BbsEntityServices.GetBbsTags("1234567", 0, 1);
            Assert.AreEqual(1, tags.Count());

            tags = BbsEntityServices.GetBbsTags("1234567", 1, 20);
            Assert.AreEqual(1, tags.Count());

            var tagedEntities = BbsEntityServices.GetBbsEntities("1234567", 0, 20).ToList();
            Assert.AreEqual( entities.Count, tagedEntities.Count );

            int count = BbsEntityServices.GetBbsTagedEntitiesCount("1234567","tag1");
            Assert.AreEqual(1, count);

            var taged = BbsEntityServices.GetBbsEntityByTag("1234567", "tag1", 0, 20).ToList();
            Assert.AreEqual(1,taged.Count);
            Assert.AreEqual("test2", taged[0].Title);

            BbsEntityServices.RemoveTagFromBbsEntity("1234567",taged[0].RowKey,"tag1");
            taged = BbsEntityServices.GetBbsEntityByTag("1234567", "tag1", 0, 20).ToList();
            Assert.AreEqual(0, taged.Count);

            count = BbsEntityServices.GetBbsTagedEntitiesCount("1234567", "tag1");
            Assert.AreEqual(0, count);
        }
    }
}
